﻿using System;
using System.Linq;
using System.Web.UI.WebControls.WebParts;

namespace Trentacular.SharePoint.Features.Web.UI.WebParts
{
    /// <summary>
    /// Serves as the base class to Web Parts with associated Editor Parts
    /// configured using the <see cref="EditorPartAttribute" /> attribute.
    /// </summary>
    public class WebEditableWebPart : BaseWebPart
    {
        /// <summary>
        /// Returns a collection of custom
        /// <see cref="T:System.Web.UI.WebControls.WebParts.EditorPart"/> controls that
        /// can be used to edit a
        /// <see cref="T:System.Web.UI.WebControls.WebParts.WebPart"/> control when it
        /// is in edit mode.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Web.UI.WebControls.WebParts.EditorPartCollection"/>
        /// that contains custom
        /// <see cref="T:System.Web.UI.WebControls.WebParts.EditorPart"/> controls
        /// associated with a <see cref="T:System.Web.UI.WebControls.WebParts.WebPart"/>
        /// control.
        /// </returns>
        public override EditorPartCollection CreateEditorParts()
        {
            var editorParts = this.GetType()
                .GetCustomAttributes(typeof(EditorPartAttribute), true)
                .Cast<EditorPartAttribute>()
                .Select(a => CreateEditorPart(a))
                .ToArray();

            return new EditorPartCollection(
                base.CreateEditorParts(),
                editorParts
                );
        }

        private EditorPart CreateEditorPart(EditorPartAttribute attribute)
        {
            var editorPart = InstantiateEditorPart(attribute);
            editorPart.ID = string.Format("{0}_{1}", this.ID, attribute.ID);
            editorPart.Title = attribute.Title;
            return editorPart;
        }

        private EditorPart InstantiateEditorPart(EditorPartAttribute attribute)
        {
            if (attribute.EditorPartType != null)
                return (EditorPart)Activator.CreateInstance(attribute.EditorPartType);

            return (EditorPart)Activator.CreateInstance(
                typeof(UserControlEditorPart<>).MakeGenericType(this.GetType()),
                attribute.UserControlVirtualPath
                );
        }
    }
}
